package org.ushio.speech_module.speech.audio;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.ushio.common_module.debounce.Debounce;
import org.ushio.common_module.util.response.ResponseResult;
import org.ushio.common_module.util.response.ResultCode;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 陈红
 */
@RestController
@RequestMapping("/api/speech")
public class AudioController {

    private static final String CACHE_KEY_PREFIX = "user_recording:";
    private static final long CACHE_EXPIRATION = 60 * 60;
    private static final Logger logger = LoggerFactory.getLogger(AudioController.class);

    @Autowired
    private UserRecordingService userRecordingService;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    @Qualifier("speechRedisTemplate")
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 构建响应对象
     * @param userRecording 用户录音对象
     *                       包含用户的句子ID、得分、文本匹配得分、音高得分、音量得分、语速得分
     * @return 响应对象
     */
    private Map<String, Object> buildResponse(UserRecording userRecording) {
        Map<String, Object> response = new HashMap<>();
        response.put("sentenceId", userRecording.getSentenceId());
        response.put("score", userRecording.getScore());
        response.put("textMatchScore", userRecording.getTextMatchScore());
        response.put("pitchScore", userRecording.getPitchScore());
        response.put("intensityScore", userRecording.getIntensityScore());
        response.put("speechRateScore", userRecording.getSpeechRateScore());
        return response;
    }

    /**
     * 识别并保存用户的录音
     * @param file 录音文件
     * @param referenceText 参考文本
     * @param userId 用户ID
     * @param sentenceId 句子ID
     * @param chapterId 章节ID
     * @return 响应对象
     */
    @PostMapping("/recognize")
    @Debounce(interval = 500)
    public ResponseEntity<String> recognizeSpeech(@RequestParam("file") MultipartFile file,
                                                  @RequestParam("referenceText") String referenceText,
                                                  @RequestParam("userId") Long userId,
                                                  @RequestParam("sentenceId") Long sentenceId,
                                                  @RequestParam("chapterId") Long chapterId) throws IOException {
        try {
            // 构建缓存键
            String cacheKey = CACHE_KEY_PREFIX + userId + ":" + sentenceId + ":" + chapterId;

            // 先清除相关缓存
            deleteCache(cacheKey);
            deleteCache(CACHE_KEY_PREFIX + userId);
            deleteCache(CACHE_KEY_PREFIX + "chapter:" + chapterId);
            deleteCache("userRecording:" + userId + ":chapter:" + chapterId);

            // 调用服务层方法
            String recognitionResult = userRecordingService.recognizeAndSaveRecording(file, referenceText, userId, sentenceId, chapterId);

            // 获取最新的UserRecording对象
            UserRecording userRecording = userRecordingService.getUserRecordingByUserIdAndSentenceId(userId, sentenceId);
            if (userRecording != null) {
                // 将识别结果和录音记录存入缓存
                try {
                    String jsonString = objectMapper.writeValueAsString(userRecording);
                    redisTemplate.opsForValue().set(cacheKey, jsonString, CACHE_EXPIRATION, TimeUnit.SECONDS);
                } catch (JsonProcessingException e) {
                    logger.error("Error serializing UserRecording to cache: {}", e.getMessage(), e);
                    // 根据业务需求决定是否在这里抛出异常
                    throw new IOException("Failed to serialize UserRecording to cache", e);
                }
                return ResponseEntity.ok(objectMapper.writeValueAsString(buildResponse(userRecording)));
            } else {
                logger.error("No UserRecording found after saving.");
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error occurred while processing the request");
            }
        } catch (Exception e) {
            logger.error("Error occurred in recognizeSpeech: {}", e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error occurred while processing the request");
        }
    }

    /**
     * 根据用户ID和章节ID获取用户的录音记录
     * @param userId 用户ID
     * @param chapterId 章节ID
     * @return 响应对象
     */
    @GetMapping("/user-chapter")
    public ResponseEntity<ResponseResult<List<UserRecordingDTO>>> getUserRecordingByUserIdAndChapterId(
            @RequestParam("userId") Long userId,
            @RequestParam("chapterId") Long chapterId) {

        // 构建缓存键
        String cacheKey = "userRecording:" + userId + ":chapter:" + chapterId;

        // 从缓存中获取UserRecording列表
        String cachedRecordingsJson = (String) redisTemplate.opsForValue().get(cacheKey);
        List<UserRecording> userRecordings = null;
        if (cachedRecordingsJson != null) {
            try {
                userRecordings = objectMapper.readValue(cachedRecordingsJson, new TypeReference<List<UserRecording>>() {});
            } catch (JsonProcessingException e) {
                logger.error("Error deserializing UserRecording list from cache: {}", e.getMessage(), e);
            }
        }

        if (userRecordings == null) {
            // 如果缓存中没有记录，从数据库中查询
            userRecordings = userRecordingService.getUserRecordingByUserIdAndChapterId(userId, chapterId);
            if (userRecordings != null && !userRecordings.isEmpty()) {
                try {
                    // 将查询结果存入缓存
                    String jsonString = objectMapper.writeValueAsString(userRecordings);
                    redisTemplate.opsForValue().set(cacheKey, jsonString, CACHE_EXPIRATION, TimeUnit.SECONDS);
                } catch (JsonProcessingException e) {
                    logger.error("Error serializing UserRecording list to cache: {}", e.getMessage(), e);
                }
            } else {
                return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ResponseResult.failed(ResultCode.NOT_FOUND.getCode(), "录音记录不存在"));
            }
        }

        // 转换为DTO
        List<UserRecordingDTO> userRecordingDTOs = userRecordings.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());

        return ResponseEntity.ok(ResponseResult.success(userRecordingDTOs));
    }

    /**
     * 转换为DTO
     * @param userRecording 用户录音对象
     * @return DTO对象
     */
    private UserRecordingDTO convertToDTO(UserRecording userRecording) {
        UserRecordingDTO dto = new UserRecordingDTO();
        dto.setRecordingId(userRecording.getRecordingId());
        dto.setUserId(userRecording.getUserId());
        dto.setSentenceId(userRecording.getSentenceId());
        dto.setScore(userRecording.getScore());
        dto.setRecognitionResult(userRecording.getRecognitionResult());
        dto.setTextMatchScore(userRecording.getTextMatchScore());
        dto.setPitchScore(userRecording.getPitchScore());
        dto.setIntensityScore(userRecording.getIntensityScore());
        dto.setSpeechRateScore(userRecording.getSpeechRateScore());
        return dto;
    }

    /**
     * 删除缓存
     * @param cacheKey 缓存键
     */
    private void deleteCache(String cacheKey) {
        redisTemplate.delete(cacheKey);
    }
}